# asterisk-realtime.pm
# Copyright (C) 2006  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

# This file is part of the CarrierClass.net project.
# For more information: http://carrierclass.net/
#
package CCNv2::Provision::Asterisk::realtime;
use strict;
use warnings;
use base qw(CCNCore::Provision::Base);
use CCN::Text;
use CCNCore::Scripting;
use CCNCore::Home;

sub run()
{
    my $self = shift;
    return unless defined $self->p->{cp_member};

    $self->CHECKFOR ('/usr/lib/asterisk/modules/res_config_mysql.so');
    $self->CHECKFOR ('/usr/lib/asterisk/modules/app_addon_sql_mysql.so');

    my $SALT = $self->system_salt;

    # For Debian:
    #    [etch as of 2006/11/07]
    #    aptitude install asterisk-dev
    #    aptitude install libmysqlclient15-dev
    #    wget http://ftp.digium.com/pub/asterisk/asterisk-addons-1.2-current.tar.gz
    #    tar xzvf asterisk-addons-1.2-current.tar.gz
    #    cd asterisk-addons-1.2.*/
    #    make res_config_mysql.so
    #    make app_addon_sql_mysql.so
    #    mv res_config_mysql.so app_addon_sql_mysql.so /usr/lib/asterisk/modules/
    # For Redhat based:
    #    yum install asterisk-addons
    #

    my $cp_db_cluster = $self->sql_get(q(SELECT db_cluster FROM cluster WHERE pk = ?),$self->p->{cp_member});

    return $self->error ("Call-processing cluster ".$self->p->{cp_member}." does not use a database cluster.")
        if not defined $cp_db_cluster;

    my @cp_db_servers = $self->sql_get_array(q(SELECT pk FROM server WHERE db_member = ?),$cp_db_cluster);
    # TBD Need load-balancing for database...
    my $cp_db_server = $cp_db_servers[0];
    $cp_db_server = $self->p->server_pk if grep { $self->p->server_pk == $_ } @cp_db_servers;
    my $DB_SERVER_IP = $self->get_replication_ip_of( $cp_db_server );

    # See db_asterisk.pm
    my $DB_PASS = $self->make_password($cp_db_cluster,$SALT,$self->p->server_pk,'asterisk');

    # There seem to be a bug with how DBD::SQLite (I assume) figures out the type of the pk
    # field in this query. It probably doesn't help that db_names is a SQL view, not a table.
    # In any case, since db_member is an INTEGER this shouldn't be a big issue.
    my $DB_NAME = $self->sql_get(q(SELECT db_name FROM db_names WHERE type = 'cp' AND pk = ).$self->p->{cp_member});

    foreach('/etc/asterisk/res_mysql.conf')
    {
        CAT $_, <<"EOT";
[general]
dbhost = ${DB_SERVER_IP}
dbname = ${DB_NAME}
dbuser = asterisk
dbpass = ${DB_PASS}
dbport = 3306
dbsock = /var/run/mysqld/mysqld.sock
EOT

        IF_CHANGED $_ => CCNv2::Scripting::AST('reload res_config_mysql.so');
}

    foreach('/etc/asterisk/config/extensions.db.conf')
    {
        CAT $_, <<"EOT";
SQL_SERVER = ${DB_SERVER_IP}
SQL_USER   = asterisk
SQL_PASS   = ${DB_PASS}
SQL_DB     = ${DB_NAME}
EOT
        IF_CHANGED $_ => CCNv2::Scripting::AST('extensions reload');
    }

    if( defined $self->p->{vm_member} )
    {
        # Note: can't use type = 'vm' since the table isn't create that way. 
        #       Not that it is really important anyway.
        my $DB_NAME = $self->sql_get(q(SELECT db_name FROM db_names WHERE type = 'cp' AND pk = ).$self->p->{vm_member});

        foreach('/etc/asterisk/extconfig.conf')
        {
            CAT $_, <<"EOT";
[settings]
voicemail => mysql,${DB_NAME},voicemail_users
EOT
            IF_CHANGED $_ => CCNv2::Scripting::AST('reload app_voicemail.so');
            IF_CHANGED $_ => CCNv2::Scripting::AST('reload app_hasnewvoicemail.so');
        }

        # YYY vm-synchronize need to be rewritten to access the database directly...
        my @vm_servers = grep { $_ != $self->p->server_pk } $self->sql_get_array(q(SELECT pk FROM server WHERE cp_member = ?),$self->p->{cp_member});

        my $data = {
            'SERVER'        => $self->get_replication_ip_of($self->p->server_pk),
            'SYSNAME'       => $self$self->p->system_name,
            'DB_NAME'       => $DB_NAME,
            'DB_SERVER_IP'  => $DB_SERVER_IP,
            'DB_PASS'       => $DB_PASS,
            'VM_SERVERS'    => join(' ', map { $self->get_replication_ip_of($_) } @vm_servers),
            'VM_SERVER_PKS' => join(' ', @vm_servers),
            'VMPATH'        => $self->p->{vmpath},
        };

        foreach(CCNCore::Home::config.'/local/bin/vm-synchronize.pl')
        {
            template(CCNCore::Home::manager.'/lib/templates/vm-synchronize.pl', $_, $data);
            IF_CHANGED '', "chmod +x $_";
            # Normally vm-synchronize is ran automatically by jabber-remote IPC.
            # This forces synchronization every 15 minutes in case the IPC would broke.
        }

    } # if vm_server

    COMMIT_MODULE(ref($self));
}

sub commit()
{
    my $self = shift;
    
    if( defined $self->p->{vm_member} )
    {
        use CCNCore::Scripting;
        CCNCore::Scripting::CRONTAB q(*/15 * * * * ).CCNCore::Home::manager.q(/bin/spool.pl synchronize-vm);
    }
}

1;
